#include "stdafx.h"
#include "ckMSEProcessor.h"

namespace ck
{
	namespace algorithm
	{
		namespace raster
		{
			MSEProcessor::MSEProcessor()
			{
				m_pBand1 = NULL;
				m_pBand2 = NULL;
				m_mse = 0.0;
			}


			MSEProcessor::~MSEProcessor()
			{
				if (m_pBand1)
				{
					m_pBand1->Release();
					m_pBand1 = NULL;
				}

				if (m_pBand2)
				{
					m_pBand2->Release();
					m_pBand2 = NULL;
				}
			}

			RESULTCODE MSEProcessor::Execute()
			{
				if (!m_pBand1 || !m_pBand2)
				{
					return RC_FAILURE;
				}

				z_uint32 w1, h1, w2, h2;
				w1 = m_pBand1->GetWidth();
				h1 = m_pBand1->GetHeight();
				w2 = m_pBand2->GetWidth();
				h2 = m_pBand2->GetHeight();
				if ((w1 != w2) || (h1 != h2))
				{
					return RC_FAILURE;
				}

				ck::data::ckPixelType type1, type2;
				type1 = m_pBand1->GetPixelType();
				type2 = m_pBand2->GetPixelType();
				if (type1 != type2)
				{
					return RC_FAILURE;
				}

				RESULTCODE rc = RC_FAILURE;
				switch (type1)
				{
				case ck::data::ckPixelTypeByte:
					rc = Calculate_Byte();
					break;
				case ck::data::ckPixelTypeUInt16:
					rc = Calculate_UInt16();
					break;
				}

				return RC_SUCCESS;
			}

			void MSEProcessor::SetBand(data::RasterBand* pBand1, data::RasterBand* pBand2)
			{
				m_pBand1 = pBand1;
				m_pBand2 = pBand2;
				if (m_pBand1)
				{
					m_pBand1->AddRef();
				}
				if (m_pBand2)
				{
					m_pBand2->AddRef();
				}
			}

			RESULTCODE MSEProcessor::Calculate_Byte()
			{
				RESULTCODE rc = RC_FAILURE;
				rc = m_pBand1->ReadData();
				rc = m_pBand2->ReadData();

				z_byte* pd1 = (z_byte*)m_pBand1->GetData();
				z_byte* pd2 = (z_byte*)m_pBand2->GetData();

				z_uint64 w = m_pBand1->GetWidth();
				z_uint64 h = m_pBand2->GetHeight();
				z_uint64 wh = w * h;

				double sum = 0;
				for (z_uint64 i = 0; i < wh; i++, pd1++, pd2++)
				{
					sum = pow((*pd1-*pd2), 2);
				}
				
				m_mse = sum / wh;

				m_pBand1->ReleaseData();
				m_pBand2->ReleaseData();

				return RC_FAILURE;
			}

			RESULTCODE MSEProcessor::Calculate_UInt16()
			{
				return RC_FAILURE;
			}

			double MSEProcessor::GetValue()
			{
				return m_mse;
			}
		}
	}
}